/**
 * =============================================================================
 * 流式聊天助手工具类
 * =============================================================================
 * 
 * 版权声明：
 * 作者：衡森
 * QQ：191118032
 * 微信：huangsentianzhenkeai
 * 
 * 功能说明：
 * 使用微信小程序原生 enableChunked API 实现真正的流式输出
 * 基于 TopThink Bot API: https://doc.topthink.com/think-bot/api.html
 * 
 * 注意事项：
 * 1. 需要微信小程序基础库版本 >= 2.20.1
 * 2. 必须替换 apiToken 为你自己的 Token
 * 3. 仅支持微信小程序环境
 * 
 * =============================================================================
 */

import Taro from '@tarojs/taro';

interface ChatOptions {
  query: string;
  conversation?: number;
  stream?: boolean;
  model?: string;
}

export const streamChatHelper = {
  
  // API 配置
  apiUrl: 'https://bot.topthink.com/api/chat',
  apiToken: 'YOUR_API_TOKEN_HERE',  // ⚠️ 请替换为你自己的 API Token
  
  /**
   * 流式聊天请求（真正的流式传输）
   * 使用微信小程序的 enableChunked + onChunkReceived 实现
   * 
   * @param message 用户消息
   * @param conversation 会话ID（可选）
   * @param onChunk 内容回调函数
   * @param onError 错误回调函数
   * @param onConversationId 会话ID回调函数
   * @param onStats 统计信息回调函数
   */
  async streamChat(
    message: string, 
    conversation?: number,
    onChunk?: (content: string, isComplete: boolean) => void,
    onError?: (error: any) => void,
    onConversationId?: (conversationId: number) => void,
    onStats?: (stats: any) => void
  ) {
    try {
      // 构建请求数据
      const requestData: ChatOptions = {
        query: message,
        stream: true,
        ...(conversation && { conversation })
      };

      let buffer = '';
      let fullContent = '';
      let hasReceivedData = false;
      let isDone = false;

      // ✅ 使用微信小程序原生 API 实现真正的流式传输
      const requestTask = Taro.request({
        url: this.apiUrl,
        method: 'POST',
        enableChunked: true, // 🔥 关键：启用分块传输（基础库 2.20.1+）
        header: {
          'Authorization': `Bearer ${this.apiToken}`,
          'Content-Type': 'application/json'
        },
        data: requestData,
        timeout: 60000,
        
        success: (res) => {
          // 降级方案：如果没有收到数据块，处理完整响应
          if (!hasReceivedData && res.data) {
            this.processFallbackResponse(res.data, onChunk, onConversationId, onStats);
          } else if (fullContent && !isDone) {
            isDone = true;
            onChunk?.(fullContent, true);
          }
        },
        
        fail: (error) => {
          console.error('❌ 流式请求失败:', error);
          onError?.(error);
        }
      });

      // ✅ 监听数据块接收事件
      requestTask.onChunkReceived((res) => {
        if (isDone) return;
        
        hasReceivedData = true;
        
        try {
          let chunk = '';
          
          // 处理不同的数据格式
          if (res.data) {
            if (typeof res.data === 'string') {
              chunk = res.data;
            } else if (res.data instanceof ArrayBuffer) {
              try {
                // 使用 TextDecoder 解码 ArrayBuffer
                if (typeof TextDecoder !== 'undefined') {
                  const decoder = new TextDecoder('utf-8');
                  chunk = decoder.decode(res.data, { stream: true });
                } else {
                  // 降级方案：手动转换
                  const uint8Array = new Uint8Array(res.data);
                  const charArray: string[] = [];
                  for (let i = 0; i < uint8Array.length; i++) {
                    charArray.push(String.fromCharCode(uint8Array[i]));
                  }
                  chunk = decodeURIComponent(escape(charArray.join('')));
                }
              } catch (decodeError) {
                console.error('❌ 解码失败:', decodeError);
                return;
              }
            }
          }
          
          // 将新数据追加到缓冲区
          buffer += chunk;
          
          // 处理缓冲区中的完整 SSE 消息
          const lines = buffer.split('\n');
          buffer = lines.pop() || '';
          
          // 处理每一行数据
          for (const line of lines) {
            if (line.startsWith('data: ')) {
              const dataStr = line.substring(6).trim();
              
              // 检查是否完成
              if (dataStr === '[DONE]') {
                isDone = true;
                onChunk?.(fullContent, true);
                return;
              }
              
              try {
                const data = JSON.parse(dataStr);
                
                // 处理会话ID
                if (data?.conversation && onConversationId) {
                  onConversationId(data.conversation);
                }
                
                // 处理统计信息
                if (data?.stats && onStats) {
                  onStats(data.stats);
                }
                
                // 处理内容块
                if (data?.chunks?.content) {
                  const content = data.chunks.content;
                  fullContent += content;
                  onChunk?.(fullContent, false);
                }
              } catch (parseError) {
                // 忽略解析错误
              }
            }
          }
        } catch (error) {
          console.error('❌ 处理数据块失败:', error);
        }
      });

      return requestTask;
    } catch (error) {
      console.error('❌ 流式请求异常:', error);
      onError?.(error);
      throw error;
    }
  },

  /**
   * 降级方案：当不支持流式传输时，处理完整响应
   */
  processFallbackResponse(
    responseData: any, 
    onChunk?: (content: string, isComplete: boolean) => void,
    onConversationId?: (conversationId: number) => void,
    onStats?: (stats: any) => void
  ) {
    let fullContent = '';
    
    if (responseData?.conversation && onConversationId) {
      onConversationId(responseData.conversation);
    }
    
    if (responseData?.stats && onStats) {
      onStats(responseData.stats);
    }
    
    if (responseData?.chunks && Array.isArray(responseData.chunks)) {
      responseData.chunks.forEach((chunk: any) => {
        if (chunk?.content) {
          fullContent += chunk.content;
        }
      });
    } else if (responseData?.content) {
      fullContent = responseData.content;
    } else if (responseData?.message) {
      fullContent = responseData.message;
    }
    
    if (fullContent) {
      // 使用打字机效果模拟流式输出
      this.simulateTypingEffect(fullContent, onChunk, 40);
    } else {
      onChunk?.('抱歉，未能获取到有效响应。', true);
    }
  },

  /**
   * 非流式聊天请求（普通请求）
   * 
   * @param message 用户消息
   * @param conversation 会话ID（可选）
   * @param model 模型名称（可选）
   * @returns Promise<any>
   */
  async chat(
    message: string,
    conversation?: number,
    model?: string
  ): Promise<any> {
    try {
      const requestData: ChatOptions = {
        query: message,
        stream: false,
        ...(conversation && { conversation }),
        ...(model && { model })
      };

      const result = await Taro.request({
        url: this.apiUrl,
        method: 'POST',
        header: {
          'Authorization': `Bearer ${this.apiToken}`,
          'Content-Type': 'application/json'
        },
        data: requestData,
        timeout: 30000
      });

      return result.data;
    } catch (error) {
      console.error('❌ 聊天请求失败:', error);
      throw error;
    }
  },

  /**
   * 模拟打字机效果（逐字显示）
   * 用于不支持真实流式输出时的降级方案
   * 
   * @param fullText 完整文本
   * @param onChunk 回调函数
   * @param speed 每个字符的显示间隔（毫秒）
   */
  async simulateTypingEffect(
    fullText: string,
    onChunk?: (content: string, isComplete: boolean) => void,
    speed: number = 50
  ) {
    let displayedText = '';
    const chars = Array.from(fullText); // 处理 emoji 和多字节字符
    
    for (let i = 0; i < chars.length; i++) {
      displayedText += chars[i];
      const isComplete = i === chars.length - 1;
      
      onChunk?.(displayedText, isComplete);
      
      if (!isComplete) {
        await new Promise(resolve => setTimeout(resolve, speed));
      }
    }
  }
};

export default streamChatHelper;

